#include "FaceAction.h"

FaceAction::FaceAction (SeetaImageData &imgData, SeetaRect &fRect, std::string modelpath)
{
	init_ImageData (imgData, fRect);
	contructContent (modelpath);
}
FaceAction::FaceAction (cv::Mat &imgMat, SeetaRect &fRect, std::string modelpath)
{
	init_Mat (imgMat, fRect);
	contructContent (modelpath);
}
void FaceAction::init_ImageData (SeetaImageData &imgData, SeetaRect &fRect)
{
	this->imgData = &imgData;
	cv::Mat mat (imgData.height, imgData.width, CV_8UC3, imgData.data);
	this->imgMat = mat;
	cv::cvtColor (mat.clone(), imgMat_gray, cv::COLOR_BGR2GRAY);
	this->imgData_gray = new SeetaImageData();
	this->imgData_gray->data = imgMat_gray.data;
	this->imgData_gray->channels = imgMat_gray.channels();
	this->imgData_gray->width = imgMat_gray.cols;
	this->imgData_gray->height = imgMat_gray.rows;
	this->fRect = &fRect;
}
void FaceAction::init_Mat (cv::Mat &imgMat, SeetaRect &fRect)
{
	cv::Mat mat (imgMat);
	this->imgMat = mat;
	cv::cvtColor (mat.clone(), imgMat_gray, cv::COLOR_BGR2GRAY);
	this->imgData = new SeetaImageData();
	this->imgData->data = imgMat.data;
	this->imgData->channels = imgMat.channels();
	this->imgData->width = imgMat.cols;
	this->imgData->height = imgMat.rows;
	this->imgData_gray = new SeetaImageData();
	this->imgData_gray->data = imgMat_gray.data;
	this->imgData_gray->channels = imgMat_gray.channels();
	this->imgData_gray->width = imgMat_gray.cols;
	this->imgData_gray->height = imgMat_gray.rows;
	this->fRect = &fRect;
}

void FaceAction::contructContent (std::string modelpath)
{
	this->modelpath = modelpath;
	seeta::ModelSetting s68;
	s68.set_id (0);
	s68.append (modelpath + "face_landmarker_pts68.csta");
	this->flm68 = new seeta::FaceLandmarker (s68);
	seeta::ModelSetting s5;
	s5.set_id (0);
	s5.append (modelpath + "face_landmarker_pts5.csta");
	this->flm5 = new seeta::FaceLandmarker (s5);
	seeta::ModelSetting se;
	se.set_id (0);
	se.append (modelpath + "eye_state.csta");
	this->ESD = new seeta::EyeStateDetector (se);
	seeta::ModelSetting setFD;
	setFD.set_id (0);
	setFD.append (modelpath + "face_detector.csta");
	this->FD = new seeta::FaceDetector (setFD);
	seeta::ModelSetting setQP;
	setQP.set_id (0);
	setQP.append (modelpath + "pose_estimation.csta");
	this->QP = new seeta::QualityOfPoseEx (setQP);
}

void FaceAction::init_points (std::vector<SeetaPointF> &i_points5,
                              std::vector<SeetaPointF> &i_points68)
{

	this->i_points5 = &i_points5;
	this->i_points68 = &i_points68;
	if (i_points5.empty() || i_points68.empty())
		std::cout << "points is empty!" << std::endl;
	else {
		SeetaPointF pts[5];
		for (int m = 0; m < 5; m++) {
			pts[m].x = this->points5->at (m).x;
			pts[m].y = this->points5->at (m).y;
		}
		checkRes = this->QP->check (*this->imgData, *this->fRect, pts, -1);
		if (checkRes.score < 0.8 && checkRes.score < 0.9) {
			std::cout << "初始化失败，请正对摄像头！！" << checkRes.score << std::endl;
			return;
		}
		this->i_points5 = &i_points5;
		this->i_points68 = &i_points68;
		INIT_TURNUP_ANGLE = calcAngle (0, 30, 4);
		INIT_TURNLEFT_ANGLE = calcAngle (16, 30, 12);
		INIT_TURNRIGHT_ANGLE = calcAngle (36, 30, 45);
	}
	INIT = 1;
}

void FaceAction::setPoints (std::vector<SeetaPointF> &points)
{
	if (points.empty())
		std::cout << "points is empty!" << std::endl;
	else if (points.size() == 5)
		this->points5 = &points;
	else
		this->points68 = &points;
}
int FaceAction::distance (int d1, int d2)
{
	double x1 = this->points68->at (d1).x;
	double y1 = this->points68->at (d1).y;
	double x2 = this->points68->at (d2).x;
	double y2 = this->points68->at (d2).y;
	return int (sqrt ( (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));
}
int FaceAction::calcAngle (int d1, int d2, int d3)
{
	/*
	d1:第一个端点；
	d2:中间顶点；
	d3:第二个端点；
	*/
	double x1 = this->points68->at (d1).x;
	double y1 = this->points68->at (d1).y;
	double x2 = this->points68->at (d2).x;
	double y2 = this->points68->at (d2).y;
	double x3 = this->points68->at (d3).x;
	double y3 = this->points68->at (d3).y;
	double numerator = (x1 - x2) * (x3 - x2) + (y3 - y2) * (y1 - y2);
	double denumerator = sqrt ( ( (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) * ( (x3 - x2) *
	                            (x3 - x2) + (y3 - y2) * (y3 - y2)));
	//std::cout << "分子 ：" << numerator << ",分母 ：" << denumerator << std::endl;
	return int (std::acos (numerator / denumerator) * 180 / 3.1415926);
}
int FaceAction::checkMouth()
{
	if (distance (61, 67) <= 10 && distance (62, 66) < 10 && distance (63, 65) < 10 &&
	    OPEN_MOUTH != 1) {
		if (OPEN_MOUTH == 0)
			OPEN_MOUTH = 1;
		if (OPEN_MOUTH == 2) {
			OPEN_MOUTH = 3;
			std::cout << "你完成了一次张嘴动作" << std::endl;
			OPEN_MOUTH = 1;
			return 7;
		}
	}
	if (distance (61, 67) > 20 && distance (62, 66) > 20 && distance (63, 65) > 20)
		OPEN_MOUTH = 2;
	return 0;
}
int FaceAction::checkTurn (int turnType)
{
	/*
	左偏头对应角度：0_30_4；
	右偏头对应角度：16_30_12；
	上偏头对应角度：36_30_45；
	*/
	int angle;
	switch (turnType) {
		case 4:
			angle = calcAngle (0, 30, 4);
			if (abs (angle - INIT_TURNLEFT_ANGLE) < 20 && TURN_LEFT != 1) {
				if (TURN_LEFT == 0)
					TURN_LEFT = 1;
				if (TURN_LEFT == 2) {
					TURN_LEFT = 3;
					std::cout << "你完成了一个左偏头动作" << std::endl;
					TURN_LEFT = 1;
					return TURN_LEFT_ACTION;
				}
			}
			if (angle - INIT_TURNLEFT_ANGLE > 40 && TURN_LEFT == 1)
				TURN_LEFT = 2;
			break;
		case 5:
			angle = calcAngle (16, 30, 12);
			if (abs (angle - INIT_TURNRIGHT_ANGLE) < 20 && TURN_RIGHT != 1) {
				if (TURN_RIGHT == 0)
					TURN_RIGHT = 1;
				if (TURN_RIGHT == 2) {
					TURN_RIGHT = 3;
					std::cout << "你完成了一个右偏头动作" << std::endl;
					TURN_RIGHT = 1;
					return TURN_RIGHT_ACTION;
				}
			}
			if (angle - INIT_TURNRIGHT_ANGLE > 40 && TURN_RIGHT == 1)
				TURN_RIGHT = 2;
			break;
		case 6:
			angle = calcAngle (17, 33, 26);
			UP_FRAMES++;
			if (abs (angle - INIT_TURNUP_ANGLE) < 20 && TURN_UP != 1) {
				if (TURN_UP == 0) {
					UP_FRAMES = 0;
					TURN_UP = 1;
				}
				if (TURN_UP == 2) {
					if (UP_FRAMES < 10) {
						std::cout << "请动作慢一点！" << std::endl;
						TURN_UP = 1;
						UP_FRAMES = 0;
						return 0;
					} else {
						TURN_UP = 3;
						std::cout << "你完成了一个上偏头动作" << UP_FRAMES << std::endl;
						UP_FRAMES = 0;
						TURN_UP = 1;
					}
					return TURN_UP_ACTION;
				}
			}
			if (angle - INIT_TURNUP_ANGLE > 25 && TURN_UP == 1)
				TURN_UP = 2;
			break;
		default:
			break;
	}
	return 0;
}

int FaceAction::checkAllTurn()
{
	int UP_RES = checkTurn (TURN_UP_ACTION);
	int LEFT_RES = checkTurn (TURN_LEFT_ACTION);
	int RIGHT_RES = checkTurn (TURN_RIGHT_ACTION);
	//if (UP_RES == TURN_UP_TYPE) return TURN_UP_TYPE;
	//if (LEFT_RES == TURN_LEFT_TYPE)return TURN_LEFT_TYPE;
	//if (RIGHT_RES == TURN_RIGHT_TYPE) return TURN_RIGHT_TYPE;
	return 0;
}
void FaceAction::setPoints68()
{

	this->points68 = new std::vector<SeetaPointF> (flm68->mark (*this->imgData_gray, *this->fRect));
}

void FaceAction::setPoints5()
{
	this->points5 = new std::vector<SeetaPointF> (flm5->mark (*this->imgData_gray, *this->fRect));
}

cv::Mat FaceAction::drawPoints (int pointsSize, bool showNumber)
{
	std::vector<SeetaPointF> points;
	if (pointsSize == 5) {
		this->setPoints5();
		points = *this->points5;
	} else {
		this->setPoints68();
		points = *this->points68;
	}
	int i = 0;
	cv::Mat resMat = (this->imgMat).clone();
	for (auto point : points) {
		if (showNumber)
			cv::putText (resMat, std::to_string (i), cv::Point (point.x, point.y), cv::FONT_HERSHEY_COMPLEX,
			             0.5, CV_RGB (255, 0, 242), 1);
		cv::circle (resMat, cv::Point (point.x, point.y), 2, (0, 0, 0), 2);
		i++;
	}
	return resMat;
}

cv::Mat FaceAction::drawPoints (int pointsSize, cv::Mat &mat, bool showNumber)
{
	std::vector<SeetaPointF> points;
	if (pointsSize == 5)
		points = *this->points5;
	else
		points = *this->points68;
	int i = 0;
	cv::Mat resMat = mat.clone();
	for (auto point : points) {
		if (showNumber) {
			cv::putText (resMat, std::to_string (i), cv::Point (point.x, point.y),
			             cv::FONT_HERSHEY_COMPLEX, 0.5, CV_RGB (0, 255, 0), 1);
		}
		cv::circle (resMat, cv::Point (point.x, point.y), 2, (0, 0, 0), 2);
		i++;
	}
	return resMat;
	
}

EYESTATE_PAIR FaceAction::getEyestate()
{
	SeetaPointF pts[5];
	for (int m = 0; m < 5; m++) {
		pts[m].x = this->points5->at (m).x;
		pts[m].y = this->points5->at (m).y;
	}
	checkRes = this->QP->check (*this->imgData, *this->fRect, pts, -1);
	seeta::EyeStateDetector::EYE_STATE leftstate, rightstate;
	this->ESD->Detect (*this->imgData, pts, leftstate, rightstate);
	return EYESTATE_PAIR (leftstate, rightstate);
}
int FaceAction::checkEyes (seeta::EyeStateDetector::EYE_STATE leftstate,
                           seeta::EyeStateDetector::EYE_STATE rightstate, int eyeType)
{
	std::map<seeta::EyeStateDetector::EYE_STATE, std::string> eyeStates;
	eyeStates[seeta::EyeStateDetector::EYE_CLOSE] = "闭眼";
	eyeStates[seeta::EyeStateDetector::EYE_OPEN] = "睁眼";
	eyeStates[seeta::EyeStateDetector::EYE_RANDOM] = "随机";
	eyeStates[seeta::EyeStateDetector::EYE_UNKNOWN] = "不确定";
	if (LEFT_BLINK == 0 && RIGHT_BLINK == 0 && ALL_BLINK == 0 &&
	    (leftstate == seeta::EyeStateDetector::EYE_UNKNOWN ||
	     rightstate == seeta::EyeStateDetector::EYE_UNKNOWN)) {
		LEFT_BLINK = 0;
		RIGHT_BLINK = 0;
		ALL_BLINK = 0;
	}
	switch (eyeType) {
		case 1:
			if (leftstate == seeta::EyeStateDetector::EYE_OPEN &&
			    rightstate == seeta::EyeStateDetector::EYE_OPEN) {
				if (LEFT_BLINK == 0)
					LEFT_BLINK = 1;
				if (LEFT_BLINK == 2)
					LEFT_BLINK = 3;
			}
			if (leftstate == seeta::EyeStateDetector::EYE_CLOSE
			    && rightstate == seeta::EyeStateDetector::EYE_OPEN
			    && LEFT_BLINK == 1)
				LEFT_BLINK = 2;
			if (LEFT_BLINK == 3) {
				std::cout << "你眨了左眼" << std::endl;
				LEFT_BLINK = 0;
				return 3;
			}
			break;
		case 2:
			if (leftstate == seeta::EyeStateDetector::EYE_OPEN &&
			    rightstate == seeta::EyeStateDetector::EYE_OPEN) {
				if (RIGHT_BLINK == 0)
					RIGHT_BLINK = 1;
				if (RIGHT_BLINK == 2)
					RIGHT_BLINK = 3;
			}
			if (leftstate == seeta::EyeStateDetector::EYE_OPEN
			    && rightstate == seeta::EyeStateDetector::EYE_CLOSE
			    && RIGHT_BLINK == 1)
				RIGHT_BLINK = 2;
			if (RIGHT_BLINK == 3) {
				std::cout << "你眨了右眼" << std::endl;
				RIGHT_BLINK = 0;
				return 3;
			}
			break;
		case 3:
			if (leftstate == seeta::EyeStateDetector::EYE_OPEN &&
			    rightstate == seeta::EyeStateDetector::EYE_OPEN) {
				if (ALL_BLINK == 0)
					ALL_BLINK = 1;
				if (ALL_BLINK == 2)
					ALL_BLINK = 3;
			}
			if (leftstate == seeta::EyeStateDetector::EYE_CLOSE
			    && rightstate == seeta::EyeStateDetector::EYE_CLOSE
			    && ALL_BLINK == 1)
				ALL_BLINK = 2;
			if (ALL_BLINK == 3) {
				std::cout << "你眨了双眼" << std::endl;
				ALL_BLINK = 0;
				return 3;
			}
			break;
		default:
			break;
	}
	//std::cout << "左眼状态：" << eyeStates[leftstate] << "右眼状态：" << eyeStates[rightstate] << std::endl;
	return 0;
}

int FaceAction::checkEyes (int eyeType)
{
	EYESTATE_PAIR pair = getEyestate();
	seeta::EyeStateDetector::EYE_STATE leftstate = pair.first;
	seeta::EyeStateDetector::EYE_STATE rightstate = pair.second;
	std::map<seeta::EyeStateDetector::EYE_STATE, std::string> eyeStates;
	eyeStates[seeta::EyeStateDetector::EYE_CLOSE] = "闭眼";
	eyeStates[seeta::EyeStateDetector::EYE_OPEN] = "睁眼";
	eyeStates[seeta::EyeStateDetector::EYE_RANDOM] = "随机";
	eyeStates[seeta::EyeStateDetector::EYE_UNKNOWN] = "不确定";
	if (LEFT_BLINK == 0 && RIGHT_BLINK == 0 && ALL_BLINK == 0 &&
	    (leftstate == seeta::EyeStateDetector::EYE_UNKNOWN ||
	     rightstate == seeta::EyeStateDetector::EYE_UNKNOWN)) {
		LEFT_BLINK = 0;
		RIGHT_BLINK = 0;
		ALL_BLINK = 0;
	}
	switch (eyeType) {
		case 1:
			if (leftstate == seeta::EyeStateDetector::EYE_OPEN &&
			    rightstate == seeta::EyeStateDetector::EYE_OPEN) {
				if (LEFT_BLINK == 0)
					LEFT_BLINK = 1;
				if (LEFT_BLINK == 2)
					LEFT_BLINK = 3;
			}
			if (leftstate == seeta::EyeStateDetector::EYE_CLOSE
			    && rightstate == seeta::EyeStateDetector::EYE_OPEN
			    && LEFT_BLINK == 1)
				LEFT_BLINK = 2;
			if (LEFT_BLINK == 3) {
				std::cout << "你眨了左眼" << std::endl;
				LEFT_BLINK = 0;
				return 3;
			}
			break;
		case 2:
			if (leftstate == seeta::EyeStateDetector::EYE_OPEN &&
			    rightstate == seeta::EyeStateDetector::EYE_OPEN) {
				if (RIGHT_BLINK == 0)
					RIGHT_BLINK = 1;
				if (RIGHT_BLINK == 2)
					RIGHT_BLINK = 3;
			}
			if (leftstate == seeta::EyeStateDetector::EYE_OPEN
			    && rightstate == seeta::EyeStateDetector::EYE_CLOSE
			    && RIGHT_BLINK == 1)
				RIGHT_BLINK = 2;
			if (RIGHT_BLINK == 3) {
				std::cout << "你眨了右眼" << std::endl;
				RIGHT_BLINK = 0;
				return 3;
			}
			break;
		case 3:
			if (leftstate == seeta::EyeStateDetector::EYE_OPEN &&
			    rightstate == seeta::EyeStateDetector::EYE_OPEN) {
				if (ALL_BLINK == 0)
					ALL_BLINK = 1;
				if (ALL_BLINK == 2)
					ALL_BLINK = 3;
			}
			if (leftstate == seeta::EyeStateDetector::EYE_CLOSE
			    && rightstate == seeta::EyeStateDetector::EYE_CLOSE
			    && ALL_BLINK == 1)
				ALL_BLINK = 2;
			if (ALL_BLINK == 3) {
				std::cout << "你眨了双眼" << std::endl;
				ALL_BLINK = 0;
				return 3;
			}
			break;
		default:
			break;
	}
	//std::cout << "左眼状态：" << eyeStates[leftstate] << "右眼状态：" << eyeStates[rightstate] << std::endl;
	return 0;
}

int FaceAction::checkAllEyes()
{
	EYESTATE_PAIR pair = getEyestate();
	if (checkRes.score < 0.8 && checkRes.score < 0.9) {
		std::cout << "无法检测眨眼动作，请正对摄像头！" << std::endl;
		LEFT_BLINK = 0;
		RIGHT_BLINK = 0;
		ALL_BLINK = 0;
	}
	int LEFT_RES = checkEyes (pair.first, pair.second, EYE_LEFT_BLINK_ACTION);
	int ALL_RES = checkEyes (pair.first, pair.second, EYE_ALL_BLINK_ACTION);
	int RIGHT_RES = checkEyes (pair.first, pair.second, EYE_RIGHT_BLINK_ACTION);
	if (LEFT_RES == EYE_LEFT_BLINK_ACTION)
		return EYE_LEFT_BLINK_ACTION;
	if (RIGHT_RES == EYE_RIGHT_BLINK_ACTION)
		return EYE_RIGHT_BLINK_ACTION;
	if (ALL_RES == EYE_ALL_BLINK_ACTION)
		return EYE_ALL_BLINK_ACTION;
	return 0;
}

int FaceAction::checkAllAction()
{
	int TURN_RES = checkAllTurn();
	int EYE_RES = checkAllEyes();
	int MOUTH_RES = checkMouth();
	if (MOUTH_RES != 0)
		return MOUTH_ACTION;
	if (EYE_RES != 0)
		return EYE_RES;
	if (TURN_RES != 0)
		return TURN_RES;
	return 0;
}

cv::Mat FaceAction::getEyeFrame (int eye)
{
	std::vector<cv::Point> pts;
	if (eye == LEFT) {
		std::vector<int> ids ({ 36, 37, 38, 39, 40, 41 });
		for (int i = 0; i < 6; ++i) {
			cv::Point p;
			p.x = points68->at (ids[i]).x;
			p.y = points68->at (ids[i]).y;
			pts.push_back (p);
		}
	} else {
		std::vector<int> ids ({42, 43, 44, 45, 46, 47});
		for (int i = 0; i < 6; ++i) {
			cv::Point p;
			p.x = points68->at (ids[i]).x;
			p.y = points68->at (ids[i]).y;
			pts.push_back (p);
		}
	}
	int x_max = 0, x_min = 100000, y_max = 0, y_min = 100000;
	for (auto point : pts) {
		if (x_max <= point.x)
			x_max = point.x;
		if (x_min >= point.x)
			x_min = point.x;
		if (y_max <= point.y)
			y_max = point.y;
		if (y_min >= point.y)
			y_min = point.y;
	}
	int margin = 5;
	x_max = (margin + x_max) < imgMat_gray.cols ? margin + x_max : imgMat_gray.cols - 1;
	x_min = (x_min - margin) >= 0 ? x_min - margin : 0;
	y_max = (margin + y_max) < imgMat_gray.rows ? margin + y_max : imgMat_gray.rows - 1;
	y_min = (y_min - margin) >= 0 ? y_min - margin : 0;
	int width = x_max - x_min, height = y_max - y_min;
	cv::Mat imgMask = cv::Mat (cv::Size (this->imgMat_gray.cols, this->imgMat_gray.rows), CV_8UC1);
	cv::fillPoly (imgMask, pts, CV_RGB (0, 0, 0));
	cv::Mat black_frame (cv::Size (this->imgMat_gray.cols, this->imgMat_gray.rows), CV_8UC1);
	cv::bitwise_not (this->imgMat_gray.clone(), black_frame, imgMask);
	cv::Mat eyeFrame = imgMat_gray.clone() (cv::Range (y_min, y_max), cv::Range (x_min, x_max));
	
	if (eye == LEFT) {
		LEye_InitCenter.x = width / 2;
		LEye_InitCenter.y = height / 2;
		EFrame_left = eyeFrame;
		LEye_Center.x = x_min;
		LEye_Center.y = y_min;
	} else {
		REye_InitCenter.x = width / 2;
		REye_InitCenter.y = height / 2;
		EFrame_right = eyeFrame;
		REye_Center.x = x_min;
		REye_Center.y = y_min;
	}
	//cv::Mat eyeFrame_gray = eyeFrame.clone();
	//cv::cvtColor(eyeFrame, eyeFrame_gray, cv::COLOR_BGR2GRAY);
	return eyeFrame.clone();
}

cv::Mat FaceAction::getIrisFrame (cv::Mat &eye_frame, int threshould)
{
	cv::Mat m1;
	cv::bilateralFilter (eye_frame, m1, 10, 15, 15);
	cv::Mat m2;
	//std::vector<std::vector<float>> kernel({ {1, 1, 1}, {1, 1, 1}, {1, 1, 1} });
	//cv::Mat kernel = cv::Mat::ones(cv::Size(3, 3), CV_8UC1);
	//cv::erode(m1, m2, kernel, cv::Point(-1, -1), 3);
	cv::erode (m1, m2, cv::Mat(), cv::Point (-1, -1), 3);
	cv::Mat m3;
	cv::threshold (m2, m3, threshould, 255, cv::THRESH_BINARY);
	//cv::cvtColor(m2, m2, cv::COLOR_BGR2GRAY);
	return m3;
}

float FaceAction::getIrisSize (cv::Mat iris_frame)
{
	cv::Mat frame = iris_frame (cv::Range (5, iris_frame.rows), cv::Range (5, iris_frame.cols));
	int height = frame.rows;
	int width = frame.cols;
	float nb_pixels = height * width;
	float nb_blacks = nb_pixels - cv::countNonZero (frame);
	return nb_blacks / nb_pixels;
}
int FaceAction::getBestThreshould (cv::Mat eye_frame)
{
	std::map<int, float> trials;
	float average_iris_size = 0.3;
	float iris_size = 0;
	int best_threshould = 10;
	
	for (int t = 10; t < 100; t += 5) {
		auto i = getIrisSize (getIrisFrame (eye_frame, t));
		if (abs (iris_size - average_iris_size) >= abs (i - average_iris_size)) {
			iris_size = i;
			best_threshould = t;
		}
		trials[t] = i;
		
	}
	return best_threshould;
}

void FaceAction::getEyeCenter()
{
	getEyeFrame (LEFT);
	getEyeFrame (RIGHT);
	auto leftThresh = getBestThreshould (EFrame_left);
	auto rightThresh = getBestThreshould (EFrame_right);
	auto leftIris = getIrisFrame (EFrame_left, leftThresh);
	auto rightIris = getIrisFrame (EFrame_right, rightThresh);
	//cv::imshow("left eye", EFrame_right);
	//cv::imshow("left iris", rightIris);
	
	std::vector<std::vector<cv::Point>> LContours;
	std::vector<std::vector<cv::Point>> RContours;
	cv::findContours (leftIris, LContours, cv::RETR_TREE, cv::CHAIN_APPROX_NONE);
	cv::findContours (rightIris, RContours, cv::RETR_TREE, cv::CHAIN_APPROX_NONE);
	float area = 100000;
	std::vector<cv::Point> LContour;
	std::vector<cv::Point> RContour;
	for (auto lcontour : LContours) {
		auto a = cv::contourArea (lcontour);
		if (area >= a) {
			area = a;
			LContour = lcontour;
		}
	}
	area = 100000;
	for (auto rcontour : RContours) {
		auto a = cv::contourArea (rcontour);
		if (area >= a) {
			area = a;
			RContour = rcontour;
		}
	}
	auto LMoments = cv::moments (LContour, false);
	LEye_RltCenter.x = int (LMoments.m10 / LMoments.m00);
	LEye_RltCenter.y = int (LMoments.m01 / LMoments.m00);
	LEye_Center.x += int (LMoments.m10 / LMoments.m00);
	LEye_Center.y += int (LMoments.m01 / LMoments.m00);
	auto RMoments = cv::moments (RContour, false);
	REye_RltCenter.x = int (RMoments.m10 / RMoments.m00);
	REye_RltCenter.y = int (RMoments.m01 / RMoments.m00);
	REye_Center.x += int (RMoments.m10 / RMoments.m00);
	REye_Center.y += int (RMoments.m01 / RMoments.m00);
	//cv::Mat showContours = EFrame_left.clone();
	//cv::drawContours(showContours, LContours, -1, CV_RGB(0, 255, 0), 1);
	//cv::circle(showContours, cv::Point(int(LMoments.m10 / LMoments.m00), int(LMoments.m01 / LMoments.m00)), 2, CV_RGB(255, 255, 255));
	//cv::imshow("leftContours", showContours);
}

int FaceAction::checkEyeRotation()
{
	getEyeCenter();
	float LEyeWidth = EFrame_left.cols;
	float REyeWidth = EFrame_right.cols;
	if ( (LEye_RltCenter.x / LEyeWidth) <= 0.33
	     && (REye_RltCenter.x / REyeWidth) <= 0.33
	     && (EYE_ROTATION_LEFT == 1))
		EYE_ROTATION_LEFT = 2;
	if ( (LEye_RltCenter.x / LEyeWidth) > 0.33
	     && (LEye_RltCenter.x / LEyeWidth) < 0.66
	     && (REye_RltCenter.x / REyeWidth) > 0.33
	     && (REye_RltCenter.x / REyeWidth) < 0.66) {
		if (EYE_ROTATION_LEFT == 0)
			EYE_ROTATION_LEFT = 1;
		if (EYE_ROTATION_LEFT == 2) {
			EYE_ROTATION_LEFT = 3;
			std::cout << "眼球向左移动了" << std::endl;
			EYE_ROTATION_LEFT = 0;
			return EYE_ROTATION_LEFT_ACTION;
		}
		if (EYE_ROTATION_RIGHT == 0)
			EYE_ROTATION_RIGHT = 1;
		if (EYE_ROTATION_RIGHT == 2) {
			EYE_ROTATION_RIGHT = 3;
			std::cout << "眼球向右移动了" << std::endl;
			EYE_ROTATION_RIGHT = 0;
			return EYE_ROTATION_RIGHT_ACTION;
		}
	}
	if ( (LEye_RltCenter.x / LEyeWidth) >= 0.66
	     && (REye_RltCenter.x / REyeWidth) >= 0.66
	     && EYE_ROTATION_RIGHT == 1)
		EYE_ROTATION_RIGHT = 2;
	return 0;
}

cv::Mat FaceAction::showEyeCenter (cv::Mat &mat)
{
	getEyeCenter();
	cv::circle (mat, LEye_Center, 2, CV_RGB (0, 255, 0), -1);
	cv::circle (mat, REye_Center, 2, CV_RGB (0, 255, 0), -1);
	return mat;
}
